home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 035a / bpq404.zip / SAMPLE.C < prev    next >
Text File  |  1990-01-13  |  9KB  |  411 lines

  1. /************************************************************************/
  2. /* EXAMPLE.C  Jonathan Naylor  G4KLX  13th January 1990*/
  3. /**/
  4. /* This program demonstrates the use of the INT 14H interface for*/
  5. /* applications programs to access the G8BPQ node software.*/
  6. /* The important routines have comments associated with them.*/
  7. /* It was compiled using Microsoft C 5.10, it will probably compile*/
  8. /* under Microsoft QuickC as well.*/
  9. /**/
  10. /* Any comments, queries etc about this code, should be directed to me*/
  11. /* and not to John G8BPQ. He is busy enough supporting the Node s/ware*/
  12. /* without answering questions about code he hasn't written.*/
  13. /**/
  14. /* Packet:G4KLX @ GB7DAD*/
  15. /* Address:24 Castle View Drive*/
  16. /*Cromford*/
  17. /*Matlock*/
  18. /*Derbyshire DE4 3RL*/
  19. /* Telephone:0629 822037*/
  20. /************************************************************************/
  21.  
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <conio.h>
  25. #include <time.h>
  26. #include <dos.h>
  27.  
  28. #define    TRUE    1
  29. #define    FALSE    0
  30.  
  31. int  Check_BPQ(int);
  32. void Raise_RTS(int);
  33. void Lower_RTS(int);
  34. void Send_Break(int);
  35. int  Write_TNC(int, char *, unsigned int);
  36. void Return_To_Node(int);
  37. int  Connected(char *, int);
  38. int  Read_TNC(int, char *, unsigned int);
  39. void Set_TNC(int, int);
  40. void Reset_TNC(int);
  41. void cru(char *);
  42. void Print_TNC(int);
  43. void Delay(int);
  44.  
  45. int main(int argc, char *argv[])
  46. {
  47. char callsign[15];
  48. char buffer[50];
  49. int  appl_number;
  50. int  port;
  51. int  i;
  52.  
  53. if (argc != 3)
  54. {
  55. fprintf(stderr, "Usage: example port application_number\n");
  56. exit(1);
  57. }
  58.  
  59. /* The INT 14H port number is 1 below the commonly used port*/
  60. /* numbers. eg COM1: = 0, COM2: = 1 etc.*/
  61.  
  62. port = atoi(argv[1]) - 1;
  63.  
  64. appl_number = atoi(argv[2]);
  65.  
  66. if (!Check_BPQ(port))
  67. exit(1);
  68.  
  69. Set_TNC(appl_number, port);
  70.  
  71. while (!kbhit())
  72. {
  73. if (Connected(callsign, port))
  74. {
  75. Print_TNC(port);
  76.  
  77. Send_Break(port);
  78.  
  79. strcpy(buffer, "CONV\r");
  80. Write_TNC(port, buffer, strlen(buffer));
  81. Print_TNC(port);
  82.  
  83. sprintf(buffer, "Hello %s\r", callsign);
  84. Write_TNC(port, buffer, strlen(buffer));
  85. Print_TNC(port);
  86.  
  87. strcpy(buffer, "Welcome to the G4KLX example program\r");
  88. Write_TNC(port, buffer, strlen(buffer));
  89. Print_TNC(port);
  90.  
  91. strcpy(buffer, "Bye Bye\r");
  92. Write_TNC(port, buffer, strlen(buffer));
  93. Print_TNC(port);
  94.  
  95. /* Returning the user to the Node immediately  */
  96. /* appears to lose the sent data, hence the delay */
  97.  
  98. Delay(3);
  99.  
  100. Return_To_Node(port);
  101.  
  102. Print_TNC(port);
  103. }
  104. }
  105.  
  106. Reset_TNC(port);
  107.  
  108. return(0);
  109. }
  110.  
  111. /************************************************************************/
  112. /* This checks for the G8BPQ Node signiature of X'AA55' in BOTH AX and*/
  113. /* BX. COMBIOS and related programs only return it in AX. The version*/
  114. /* number is also retrieved, this could be checked if using a newly*/
  115. /* implemented feature of the code.*/
  116. /************************************************************************/
  117.  
  118. int Check_BPQ(int port)
  119. {
  120. union REGS regs;
  121.  
  122. regs.x.dx = port;
  123. regs.h.ah = 4;
  124.  
  125. int86(0x14, ®s, ®s);
  126.  
  127. if (regs.x.ax != 0xAA55 || regs.x.bx != 0xAA55)
  128. {
  129. fprintf(stderr, "example: G8BPQ node support not loaded\n");
  130. return(FALSE);
  131. }
  132.  
  133. regs.x.dx = port;
  134. regs.h.ah = 0x1F;
  135. regs.h.al = 0;
  136.  
  137. int86(0x14, ®s, ®s);
  138.  
  139. printf("Running G8BPQ node support version %d.%d\n",
  140. regs.h.dh, regs.h.dl);
  141.  
  142. return(TRUE);
  143. }
  144.  
  145. void Raise_RTS(int port)
  146. {
  147. union REGS regs;
  148.  
  149. regs.x.dx = port;
  150. regs.h.ah = 6;
  151.  
  152. int86(0x14, ®s, ®s);
  153. }
  154.  
  155. void Lower_RTS(int port)
  156. {
  157. union REGS regs;
  158. regs.x.dx = port;
  159. regs.h.ah = 5;
  160.  
  161. int86(0x14, ®s, ®s);
  162. }
  163.  
  164. /************************************************************************/
  165. /* Sending a break to the node software is the sure-fire way of getting*/
  166. /* back to command mode from converse and transparant mode.*/
  167. /************************************************************************/
  168.  
  169. void Send_Break(int port)
  170. {
  171. union REGS regs;
  172.  
  173. regs.x.dx = port;
  174. regs.h.ah = 7;
  175.  
  176. int86(0x14, ®s, ®s);
  177. }
  178.  
  179. /************************************************************************/
  180. /* This function takes the same sort of arguments as the C library*/
  181. /* function write(). It is a non blocking function that returns when*/
  182. /* either all of the data has been sent to the node, or when the node*/
  183. /* cannot accept any more data.*/
  184. /************************************************************************/
  185.  
  186. int Write_TNC(int port, char *buffer, unsigned int count)
  187. {
  188. union REGS regs;
  189. int attempts = 0;
  190. int i;
  191.  
  192. for (i = 0; i < count; i++)
  193. {
  194. regs.x.dx = port;
  195. regs.h.ah = 3;
  196.  
  197. do
  198. {
  199. attempts++;
  200.  
  201. int86(0x14, ®s, ®s);
  202. }
  203. while (!(regs.h.ah & 0x20) && (attempts < 6));
  204.  
  205. if (attempts == 6)
  206. return(i);
  207.  
  208. attempts = 0;
  209.  
  210. regs.x.dx = port;
  211. regs.h.ah = 1;
  212. regs.h.al = buffer[i];
  213.  
  214. int86(0x14, ®s, ®s);
  215. }
  216.  
  217. return(i);
  218. }
  219.  
  220. /************************************************************************/
  221. /* This is the gracefull way of getting rid of users, until recently the*/
  222. /* only available option was to disconnect them from the node, this puts*/
  223. /* them back to the node software.*/
  224. /************************************************************************/
  225.  
  226. void Return_To_Node(int port)
  227. {
  228. union REGS regs;
  229.  
  230. regs.x.dx = port;
  231. regs.h.ah = 0x1F;
  232. regs.h.al = 0x10;
  233.  
  234. int86(0x14, ®s, ®s);
  235. }
  236.  
  237. /************************************************************************/
  238. /* This function serves two purposes, it indicates whether the*/
  239. /* application is connected to a user, and if so, what their callsign*/
  240. /* is. At present it does not return the users ssid, but it is available*/
  241. /* if needed. The code gets the users callsign from the INT 14H and not*/
  242. /* from parsing the "*** CONNECTED to ..." line. This piece of the code*/
  243. /* makes use of a far pointer to the callsign within the Node software.*/
  244. /* It then has to be converted to ASCII from AX25 format, which is*/
  245. /* essentially shifting the characters right by one bit.*/
  246. /************************************************************************/
  247.  
  248. int Connected(char *buffer, int port)
  249. {
  250. union REGS regs;
  251. struct SREGS segregs;
  252. unsigned char far *callsign;
  253. int ssid;
  254. int i;
  255.  
  256. regs.x.dx = port;
  257. regs.h.ah = 0x1F;
  258. regs.h.al = 1;
  259.  
  260. int86x(0x14, ®s, ®s, &segregs);
  261.  
  262. if (regs.x.si == 0)
  263. return(FALSE);
  264.  
  265. FP_SEG(callsign) = segregs.es;
  266. FP_OFF(callsign) = regs.x.si;
  267.  
  268. for (i = 0; (callsign[i] >> 1) != ' ' && i < 6; i++)
  269. buffer[i] = callsign[i] >> 1;
  270.  
  271. buffer[i] = '\0';
  272.  
  273. ssid = (callsign[6] >> 1) & 0x0F;
  274.  
  275. return(TRUE);
  276. }
  277.  
  278. /************************************************************************/
  279. /* This routine is a non-blocking read of the port input stream.*/
  280. /************************************************************************/
  281.  
  282. int Read_TNC(int port, char *buffer, unsigned int count)
  283. {
  284. union REGS regs;
  285. int i = 0;
  286.  
  287. regs.x.dx = port;
  288. regs.h.ah = 3;
  289.  
  290. int86(0x14, ®s, ®s);
  291.  
  292. while ((regs.h.ah & 0x01) && (i < count))
  293. {
  294. regs.x.dx = port;
  295. regs.h.ah = 2;
  296.  
  297. int86(0x14, ®s, ®s);
  298.  
  299. buffer[i++] = regs.h.al;
  300.  
  301. regs.x.dx = port;
  302. regs.h.ah = 3;
  303.  
  304. int86(0x14, ®s, ®s);
  305. }
  306.  
  307. buffer[i] = '\0';
  308.  
  309. return(i);
  310. }
  311.  
  312. void Set_TNC(int appl_number, int port)
  313. {
  314. char *command;
  315. char buffer[15];
  316.  
  317. Raise_RTS(port);
  318.  
  319. Send_Break(port);
  320.  
  321. command = "ECHO ON\r";
  322. Write_TNC(port, command, strlen(command));
  323. Print_TNC(port);
  324.  
  325. sprintf(buffer, "APPL $%02X\r", appl_number);
  326. Write_TNC(port, buffer, strlen(buffer));
  327. Print_TNC(port);
  328.  
  329. command = "MONITOR OFF\r";
  330. Write_TNC(port, command, strlen(command));
  331. Print_TNC(port);
  332.  
  333. command = "CONOK ON\r";
  334. Write_TNC(port, command, strlen(command));
  335. Print_TNC(port);
  336. }
  337.  
  338. void Reset_TNC(int port)
  339. {
  340. char *command;
  341.  
  342. Send_Break(port);
  343.  
  344. command = "APPL $00\r";
  345. Write_TNC(port, command, strlen(command));
  346. Print_TNC(port);
  347.  
  348. command = "CONOK OFF\r";
  349. Write_TNC(port, command, strlen(command));
  350. Print_TNC(port);
  351.  
  352. command = "ECHO OFF\r";
  353. Write_TNC(port, command, strlen(command));
  354. Print_TNC(port);
  355.  
  356. Lower_RTS(port);
  357. }
  358.  
  359. /************************************************************************/
  360. /* This function takes its name from a UNIX utility at Nottingham Uni*/
  361. /* called Carriage Return Utility. It converts between the carriage*/
  362. /* returns standards found on packet radio to the standards used in DOS*/
  363. /************************************************************************/
  364.  
  365. void cru(char *string)
  366. {
  367. int i;
  368.  
  369. for (i = 0; string[i] != '\0'; i++)
  370. {
  371. switch (string[i])
  372. {
  373. case '\n':
  374. string[i] = '\r';
  375. break;
  376. case '\r':
  377. string[i] = '\n';
  378. break;
  379. }
  380. }
  381. }
  382.  
  383. void Print_TNC(int port)
  384. {
  385. char buffer[100];
  386.  
  387. Read_TNC(port, buffer, 99);
  388. cru(buffer);
  389. printf("%s", buffer);
  390. }
  391.  
  392. /************************************************************************/
  393. /* Delay for n seconds. In a "real" piece of software, it would be wise*/
  394. /* to give time slices to DESQview at the point. The same can also be*/
  395. /* said of the loop in main() where it is waiting for a user.*/
  396. /************************************************************************/
  397.  
  398. void Delay(int delay)
  399. {
  400. time_t start_time;
  401. time_t current_time;
  402.  
  403. time(&start_time);
  404.  
  405. do
  406. {
  407. time(¤t_time);
  408. }
  409. while ((current_time - start_time) < delay);
  410. }
  411.